﻿using System;
using System.Linq.Expressions;
using DevExpress.Data.Filtering;

namespace EFExtention.Common.Utils {
    public class CriteriaOperatorToExpressionConverter<T> {
        public Expression<Func<T, bool>> Convert(CriteriaOperator criteria) {
            var converter = new CriteriaToExpressionConverterIgnoreEnumBinaryOperatorsWithoutParams();
            ParameterExpression parameter = Expression.Parameter(typeof(T));
            Expression body = converter.Convert(parameter, criteria);
            if(body == null)
                return null;
            return Expression.Lambda<Func<T, bool>>(body, parameter);
        }
        class CriteriaToExpressionConverterIgnoreEnumBinaryOperatorsWithoutParams {
            static ConstantExpression TrueExpression = Expression.Constant(true);
            public Expression Convert(ParameterExpression thisExpression, CriteriaOperator op) {
                return new CriteriaToExpressionConverterInternal(thisExpression).Process(op);
            }
            class CriteriaToExpressionConverterInternal : DevExpress.Data.Linq.Helpers.CriteriaToExpressionConverterInternal {
                public CriteriaToExpressionConverterInternal(ParameterExpression thisExpression)
                    : base(thisExpression) {
                }
                protected override object VisitInternal(BinaryOperator theOperator) {
                    Expression left = Process(theOperator.LeftOperand);
                    ConstantExpression right = Process(theOperator.RightOperand) as ConstantExpression;
                    if((left != null && left.Type.IsEnum) && (right != null && right.Value == null))
                        return TrueExpression;
                    return base.VisitInternal(theOperator);
                }
            }
        }
    }
}
